<?php

require_once(__DIR__."/pmvc/ClassLoader.class.php");
require_once(__DIR__."/pmvc/FileSystemClassLoader.class.php");
require_once(__DIR__."/pmvc/util/ClassUtil.class.php");

class PMVC {

	const REFLECTION_CACHE_DISABLED		= 0;
	const REFLECTION_CACHE_AUTO_DETECT	= 10;
	const REFLECTION_CACHE_USER_DEFINED	= 20;
	const REFLECTION_CACHE_APC			= 30;
	
	private static $INITIALIZED				= NULL;
	private static $REFLECTION_SAVE_CB		= NULL;
	private static $REFLECTION_GET_CB		= NULL;

	/**
	 * Called to create the PMVC object.
	 */
	private function __construct() {
		if (PMVC::$REFLECTION_GET_CB!=NULL) {
			$fn = PMVC::$REFLECTION_GET_CB;
			$data = $fn();
			if ($data!==FALSE) {
				\pmvc\util\ClassUtil::setReflectionCache($data);
			}
		}
	}

	/**
	 * Called when the PMVC object is garbage collected.
	 */
	public function __destruct() {
		if (PMVC::$REFLECTION_SAVE_CB!=NULL) {
			$fn = PMVC::$REFLECTION_SAVE_CB;
			$fn(\pmvc\util\ClassUtil::getReflectionCache());
		}
	}

	/**
	 * Initializes the PMVC framework.
	 * @param array $classpath
	 */
	public static function initialize($classpath=Array(),
		$reflectionCacheType=PMVC::REFLECTION_CACHE_DISABLED, $reflectionSaveCallback=NULL, $reflectionGetCallback=NULL) {
		if (PMVC::$INITIALIZED!=NULL) {
			throw new \Exception("PMVC is already initialized");
		}

		// setup apc reflection cache
		if ($reflectionCacheType==PMVC::REFLECTION_CACHE_APC
			|| ($reflectionCacheType==PMVC::REFLECTION_CACHE_AUTO_DETECT && function_exists("apc_exists"))) {
			PMVC::$REFLECTION_SAVE_CB = function($cacheData) {
				$existingValue = NULL;
				if (function_exists("apc_exists")
					&& function_exists("apc_fetch")
					&& apc_exists("pmvcApcRefCache")) {
					$existingValue = apc_fetch("pmvcApcRefCache");
				}
				if ($existingValue!=$cacheData && function_exists("apc_store")) {
					apc_store("pmvcApcRefCache", $cacheData);
				} else if (!function_exists("apc_store")) {
					throw new \Exception("apc caching is not available on this system");
				}
			};
			PMVC::$REFLECTION_GET_CB = function() {
				if (function_exists("apc_exists")
					&& function_exists("apc_fetch")
					&& apc_exists("pmvcApcRefCache")) {
					return apc_fetch("pmvcApcRefCache");
				} else if (function_exists("apc_fetch")) {
					return apc_fetch("pmvcApcRefCache");
				} else {
					throw new \Exception("apc caching is not available on this system");
				}
			};

		// setup user defined reflection cache
		} else if ($reflectionCacheType==PMVC::REFLECTION_CACHE_USER_DEFINED) {
			\pmvc\util\ClassUtil::setReflectionSaveCallback($reflectionSaveCallback);
			\pmvc\util\ClassUtil::setReflectionGetCallback($reflectionGetCallback);

		}

		// setup root classloader
		array_unshift($classpath, __DIR__);
		\pmvc\util\ClassUtil::addClassLoader(new \pmvc\FileSystemClassLoader($classpath));
		PMVC::$INITIALIZED = new PMVC();
	}

}

?>